#pragma once
#include <iostream>
#include <cstring>
#include <cerrno>
#include <arpa/inet.h>
#include <iostream>
#include <cstring>
#include <cerrno>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
class tcp_socket_t
{
public:
    tcp_socket_t(const uint16_t port)
    {
        // socket
        _fd = socket(AF_INET, SOCK_STREAM, 0);
        if (_fd < 0)
        {
            std::cerr << strerror(errno) << std::endl;
            exit(1);
        }
        // info
        sockaddr_in my_addr;
        bzero(&my_addr, sizeof(sockaddr_in));
        my_addr.sin_family = AF_INET;
        my_addr.sin_addr.s_addr = INADDR_ANY;
        my_addr.sin_port = htons(port);
        // may use the port again immediately after restrating the socket
        int opt = 1;
        setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
        setsockopt(_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof opt);
        // bind
        if (bind(_fd, (sockaddr *)&my_addr, sizeof(sockaddr_in)) == -1)
        {
            std::cerr << strerror(errno) << std::endl;
            exit(2);
        }
    }
    // get fd
    int get_fd() const
    {
        return _fd;
    }
    // listen
    bool listen_fd(int num) const
    {
        return listen(_fd, num) == 0;
    }
    // accept
    int accept_fd() const
    {
        sockaddr_in peer_addr;
        socklen_t peer_len = sizeof peer_addr;
        return accept(_fd, (sockaddr *)&peer_addr, &peer_len);
    }

private:
    int _fd;
};
